module arm.hal;

import chip;
import arm.cortex_m;
import arm.utils;


/**
    HAL Status structures definition

*/
enum Hal_Status : size_t
{
    None = 0x00,
    Error = 0x01,
    Busy = 0x02,
    Timeout = 0x03,
}
alias Status = Hal_Status;

/**
    HAL Lock structures definition
*/
enum Hal_Lock : size_t
{
    Unlocked = 0x00,
    Locked = 0x01,
}

final abstract class HAL
{
    /*
    enum SystemCoreClock = 16000000u;
    /// 初始化 SysTick
    static void InitTick(uint mPriority)
    {
        // 初始化系统时钟
        //SysTick.
        SysTick.setClockFreq(SystemCoreClock/(1000u));
        PrioritySet(IRQn_Core.SysTick_IRQn,mPriority,0);
        //NVIC.PrioritySet
    }
    */
    /*
    static void PrioritySet(T)(T mIrq,uint mp,uint sp)
    {
        import c_misc;
        //NVIC.PrioritySet
        auto pg = SCB.PriorityGroup;
        auto encode = NVIC_EncodePriority(pg,mp,sp);
        Utils.PrioritySet(mIrq,encode);
    }
    */

    /*
    static void PrioritySet(int mIrq,uint mPriority,uint subPriority)
    {
        import c_misc;
        //NVIC.PrioritySet
        auto pg = SCB.PriorityGroup;
        auto encode = NVIC_EncodePriority(pg,mPriority,subPriority);
        Utils.PrioritySet(mIrq,encode);
    }
    */

}

version(NONE):

/// 初始化 Hal 外设
Hal_Status Hal_Init()
{
    // 设置优先级

    // 初始化时间片
    //FLASH.ACR.ICEN.val = true;
    //FLASH.ACR.DCEN.val = true;
    //FLASH.ACR.PRFTEN.val = true;
    /* Set Interrupt Group Priority */
    /* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */
    return Hal_Status.None;
}

/// 初始化时间片
Hal_Status Hal_InitTick(uint tick)
{
    return Hal_Status.None;
}


/*
static bool haslsb(T)(T* p)
{
    return (cast(size_t)p & 1) != 0;
}

static T* setlsb(T)(T* p)
{
    return cast(T*)(cast(size_t)p | 1);
}

static T* clearlsb(T)(T* p)
{
    return cast(T*)(cast(size_t)p & ~1);
}
*/

/// 按位设置


/// 按位清除

/// 重制 Hal 外设
Hal_Status Hal_DeInit()
{
    static if (__traits(hasMember, RCC, "APB1RSTR"))
    {
        //__HAL_RCC_APB1_FORCE_RESET();
        RCC.APB1RSTR.value = uint.max;
        //__HAL_RCC_APB1_RELEASE_RESET();
        RCC.APB1RSTR.value = 0x00;
    }

    static if (__traits(hasMember, RCC, "APB2RSTR"))
    {
        //__HAL_RCC_APB2_FORCE_RESET();
        RCC.APB2RSTR.value = uint.max;
        //__HAL_RCC_APB2_RELEASE_RESET();
        RCC.APB2RSTR.value = 0x00;
    }

    static if (__traits(hasMember, RCC, "AHB1RSTR"))
    {
        //__HAL_RCC_AHB1_FORCE_RESET();
        RCC.AHB1RSTR.value = uint.max;
        //__HAL_RCC_AHB1_RELEASE_RESET();
        RCC.AHB1RSTR.value = 0x00;
    }

    static if (__traits(hasMember, RCC, "AHB2RSTR"))
    {
        //__HAL_RCC_AHB2_FORCE_RESET();
        RCC.AHB2RSTR.value = uint.max;
        //__HAL_RCC_AHB2_RELEASE_RESET();
        RCC.AHB2RSTR.value = 0x00;
    }

    static if (__traits(hasMember, RCC, "AHB3RSTR"))
    {
        //__HAL_RCC_AHB3_FORCE_RESET();
        RCC.AHB3RSTR.value = uint.max;
        //__HAL_RCC_AHB3_RELEASE_RESET();
        RCC.AHB3RSTR.value = 0x00;
    }

    return Hal_Status.None;
}

/// SysTick配置
Hal_Status SysTick_Config(uint ticks)
{
    if ((ticks -1) > STK.LOAD.RELOAD.BitMask)
    {
        return Hal_Status.Error;
    }

    STK.LOAD.RELOAD.val = ticks - 1;
    // 设置优先级

    // 重制当前值
    STK.VAL.CURRENT.val = 0;
    // 使能 SysTick
    STK.CTRL.value = STK.CTRL.CLKSOURCE.RegMask | STK.CTRL.TICKINT.RegMask | STK.CTRL.ENABLE.RegMask;

    return Hal_Status.None;
}
